// SPDX-License-Identifier: GPL-2.0 or GPL-3.0
// Copyright © 2018-2019 Ariadne Devos
/* sHT -- things to do that may block */

#ifndef _sHT_TASK_H
#define _sHT_TASK_H

#include <stddef.h>
#include <stdint.h>

#define sHT_TASK_QUEUED UINT32_C(1)
#define sHT_TASK_SCHEDULE UINT32_C(1)

/** Something to do that may block. If it would block, another task is run
    instead. It is automatically resumed. */
struct sHT_task {
	/** Indicates which IO actions might be possible */
	uint32_t epollflags;
	/** @code{sHT_TASK_QUEUED}: this task is on a queue of things to
	      do. It is automatically added by @var{sHT_qadd}.
	    @code{sHT_TASK_SCHEDULE}: this task should be put on a queue
	      of things to do. The queue and taskset code do not test,
	      set or clear this flag.
	  Feel free to add other flags of your own. */
	uint32_t flags;
	/** A pointer to the task to execute after this one, within a
	    @var{sHT_taskset}. This should not be used outside taskset
	    internals -- until this comment is changed to the contrary. */
	struct sHT_task *next;
};

/** Initialise the task @var{task}.

  This cleares its flags, and considers all IO actions to be potentially
  possible. @var{task} does not have to be initialised beforehand.

  @var{task} may not be concurrently acccessed.

  This cannot fail in any way. */
__attribute__((nonnull(1)))
static inline void
sHT_init_task(struct sHT_task *task)
{
	*task = (struct sHT_task) {
		.epollflags = ~UINT32_C(0),
		.flags = 0,
		/* TODO: in the Linux kernel, NULL is sometimes actually
		   mapped and may therefore not be speculatively accessed.
		   (In userspace, MMAP_PAGE_ZERO, to all zeros).
		   On x86-64, AMD has promised never to allow mapping a
		   certain range, use that in this case. */
		.next = NULL,
	};
}

#endif
